// Copyright 2012 dmitry.a.novikov@gmail.com
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "consistenz.h"
#include "object.h"
#include "objectimpl.h"
#include "dbobject.h"
#include "filer.h"
#include <iostream>

namespace CnsZ {

  DEFINE_CNSZ_OBJECT_CLASS(Object, NULL_FACTORY);

  const Class* CnsZ_Object_ClassImpl::parentClass() const { return 0; }

  P<Object> CnsZ_Object_ClassImpl::createInstance() const { NULL_FACTORY(Object); }

  Object::~Object() {}

  P<Object> Object::Interface( const Class* interfaceName ) const {
    const Class* cls = isA();
    while(cls) {
      if(cls==interfaceName) {
        return this;
      }
      cls = cls->parentClass();
    }
    return P<Object>();
  }

  bool Object::isKindOf( const Class* interfaceName ) const {
    const Class* cls = isA();
    while(cls) {
      if(cls==interfaceName) {
        return true;
      }
      cls = cls->parentClass();
    }
    return false;
  }

  int Object::compare(const Object* other) const {
    if(this < other) {
      return -1;
    }
    if(this > other) {
      return +1;
    }
    return 0;
  }

  void Object::copy(const Object* ) {
    THROW_STATIC(NotApplicable, L"Object::copy() not implemented.");
  }

  P<Object> Object::clone() const {
    P<Object> obj;
    const Class* cls = isA();
    if( cls ) {
      obj = cls->createInstance();
      if( obj.get() ) {
        obj->copy( this );
      }
    }
    return obj;
  }
  
  void Object::read(Filer& ) {
  }

  void Object::write(Filer& ) const {
  }

  String Object::toString() const {
    std::wostringstream s;
    s << '<' << isA()->name() << ':' << '@' << (void*)this << '>';
    return String(s.str().data());
  }

}//namespace CnsZ

std::wostream&
operator << (std::wostream& ostr, const CnsZ::Object* object) {
  if(object) {
    return ostr << object->toString();
  }
  return ostr << "NULL";
}
